package com.zyc.spring;

import com.zyc.annotation.RpcReference;
import com.zyc.annotation.RpcService;
import com.zyc.factory.SingletonFactory;
import com.zyc.provider.ServiceProvider;
import com.zyc.provider.impl.ZKServiceProviderImpl;
import com.zyc.proxy.RpcClientProxy;
import com.zyc.remoting.transport.RpcRequestTransport;
import com.zyc.remoting.transport.socket.SocketRpcClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/**
 * 创建bean前如果带有注解则先执行此类方法
 * @author zyc
 * @create 2022--05--30 20:23
 */
@Slf4j
@Component
public class SpringBeanPostProcessor implements BeanPostProcessor {
    private final ServiceProvider serviceProvider;
    private final RpcRequestTransport rpcRequestTransport;

    public SpringBeanPostProcessor() {
        this.serviceProvider = SingletonFactory.getInstance(ZKServiceProviderImpl.class);
        //TODO
        this.rpcRequestTransport = new SocketRpcClient();
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().isAnnotationPresent(RpcService.class)) {
            log.info("【{}】带有注解【{}】",bean.getClass().getName(),RpcService.class.getCanonicalName());
            RpcService rpcServiceAnnotation = bean.getClass().getAnnotation(RpcService.class);

            // TODO rpcServiceConfig
            serviceProvider.publishService(bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> targetClass = bean.getClass();
        Field[] declaredFields = targetClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            RpcReference rpcReference = declaredField.getAnnotation(RpcReference.class);
            if (rpcReference != null) {
                // TODO
                RpcClientProxy rpcClientProxy = new RpcClientProxy(rpcRequestTransport);
                Object clientProxy = rpcClientProxy.getProxy(declaredField.getType());
                declaredField.setAccessible(true);
                try {
                    declaredField.set(bean, clientProxy);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }
}
